package com.sf.algo.http;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;


/**
 * 描述：
 * 
 * <pre>HISTORY
 * ****************************************************************************
 *  ID   DATE           PERSON          REASON
 *  1    2017年11月30日      Simba.Hua         Create
 * ****************************************************************************
 * </pre>
 * @author Simba.Hua
 */
public class HttpClient {

	private static final Logger logger = LoggerFactory.getLogger(HttpClient.class);
	//编码
	private static final String CHARSET_UTF_8 = "utf-8";
	//链接池管理器 
	private static PoolingHttpClientConnectionManager pool;
	
	private static RequestConfig requestConfig;
	//重试次数
	private static final int RETRIES = 0;
	
	static {
		try {
			SSLContextBuilder builder = new SSLContextBuilder();
			builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
			SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(builder.build());
			 // 配置同时支持 HTTP 和 HTPPS
			  Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create().register(
                      "http", PlainConnectionSocketFactory.getSocketFactory()).register(
                      "https", factory).build();
              // 初始化连接管理器
              pool = new PoolingHttpClientConnectionManager(
                     socketFactoryRegistry);
              // 将最大连接数增加到200，实际项目最好从配置文件中读取这个值
              pool.setMaxTotal(200);
              // 设置最大路由
              pool.setDefaultMaxPerRoute(2);
             // 根据默认超时限制初始化requestConfig
              int socketTimeout = 20000;
              int connectTimeout = 20000;
              int connectionRequestTimeout = 20000;
              requestConfig = RequestConfig.custom().setConnectionRequestTimeout(
                      connectionRequestTimeout).setSocketTimeout(socketTimeout).setConnectTimeout(
                      connectTimeout).build();
		} catch (NoSuchAlgorithmException e) {
			logger.error("NoSuchAlgorithmException",e);
		} catch (KeyStoreException e) {
			logger.error("KeyStoreException",e);
		} catch (KeyManagementException e) {
			logger.error("KeyManagementException",e);
		}
	}
	
	private static CloseableHttpClient getHttpClient(){
		return HttpClients.custom()
				 .setConnectionManager(pool)
				 .setDefaultRequestConfig(requestConfig)
				 .setRetryHandler(new DefaultHttpRequestRetryHandler(RETRIES,true))
				 .build();
	}
	/**
	 * http post请求
	 * @param httpPost
	 * @return
	 */
	private static String sendHttpPost(HttpPost httpPost) {
		return sendHttp(httpPost);
	}
	
	private static String sendHttpGet(HttpGet httpGet) {
		return sendHttp(httpGet);
	}
	
	private static String sendHttp(HttpRequestBase httpRequest) {

		CloseableHttpClient client = null;
		CloseableHttpResponse response = null;
		String responseContext = null;
			
		try {
			client = getHttpClient();
			httpRequest.setConfig(requestConfig);
			response = client.execute(httpRequest);
			HttpEntity entity = response.getEntity();
			if (response.getStatusLine().getStatusCode() >= 300) {
				String errorInfo = "时间距离档http请求失败，返回状态码为:" + response.getStatusLine().getStatusCode();
				logger.error(errorInfo);
				throw new RuntimeException(errorInfo);
			}
			if (HttpStatus.OK.value() == response.getStatusLine().getStatusCode()) {
				responseContext = EntityUtils.toString(entity, CHARSET_UTF_8);
				EntityUtils.consume(entity);
			}
		} catch (ClientProtocolException e) {
			logger.error("ClientProtocolException",e);
		} catch (IOException e) {
			logger.error("IOException",e);
		} finally {
			if (response != null)
				try {
					response.close();
				} catch (IOException e) {
					logger.error("response closed error",e);
				}
		}
		return responseContext;
	}
	
	/**
	 * 发送请求
	 * @param url
	 * @return
	 */
	public static String sendHttpPost(String url) {
		HttpPost httpPost = new HttpPost(url);
		return sendHttpPost(httpPost);
	}
	
	public static String sendHttpGet(String url) {
		HttpGet httpGet = new HttpGet(url);
		return sendHttpGet(httpGet);
	}

}
